package com.lagou.consumer;

import com.lagou.anno.MyRpcConsumer;
import com.lagou.request.RpcRequest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//用于注入被MyRpcConsumer注解的属性，生成动态代理对象，注入到对应的属性中
@Component
public class ConsumerBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
    //启动时，需要知道所有消费者类
    public static Set<Class> classSet = new HashSet<>();
    private static ApplicationContext ac;

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //判断当前bean是否有被@MyRpcConsumer注解的属性类
        Class clazz = bean.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(MyRpcConsumer.class)) {
                //获取生产者的接口类型
                Class fieldClass = field.getType();
                ConsumerProxyObject proxyObject = new ConsumerProxyObject(fieldClass);
                Object proxy = proxyObject.createProxy();
                //将当前动态代理对象注入到属性中
                field.setAccessible(true);
                try {
                    field.set(bean, proxy);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                classSet.add(fieldClass);
            }
        }
        return bean;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ac = applicationContext;
    }


    private static class ConsumerProxyObject implements InvocationHandler {

        private static Random random = new Random();
        //1.创建一个线程池对象  -- 它要处理我们自定义事件
        public static ExecutorService executorService =
                Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        //2.声明一个自定义事件处理器  UserClientHandler
//        public static ConsumerHandler consumerHandler = (ConsumerHandler)ac.getBean("consumerHandler");
        //public ConsumerHandler consumerHandler = (ConsumerHandler)ac.getBean("consumerHandler");

        public Class interfaceClass;

        public ConsumerProxyObject(Class interfaceClass) {
            this.interfaceClass = interfaceClass;
        }

        public Object createProxy() {
            //创建动态代理对象
            return Proxy.newProxyInstance(ConsumerBeanPostProcessor.class.getClassLoader(), new Class[]{interfaceClass}, this);
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Map<String, ConsumerHandler> handlerMap = ConsumerNettyConnect.handlerMap;
            ConsumerHandler consumerHandler = null;
            //生成一个随机数，范围在map个数之间
            if(handlerMap.size() > 1){
                int i = random.nextInt(handlerMap.size());
                //随便取一个handler
                Object[] handlerArr = handlerMap.values().toArray();
                consumerHandler = (ConsumerHandler) handlerArr[i];
            }else{
                for (Map.Entry<String, ConsumerHandler> entry : handlerMap.entrySet()) {
                    consumerHandler = entry.getValue();
                }
            }

            //构建RpcRequest对象
            consumerHandler.setRequest(RpcRequest.build(interfaceClass, method, args));

            //3).使用线程池,开启一个线程处理处理call() 写操作,并返回结果
            Object result = executorService.submit(consumerHandler).get();

            //4)return 结果
            return result;
        }
    }
}
